זו התחלה כמובן. אין עוד עבודה עם database, מערכת של משתמשים וכו'.
הקונטרולר שיש שם כרגע עובד עם model שמייצג טופס הרשמה.
אפשר לראות שממש ממש קל ונוח לטפל בטפסים והעבודה ב-view מאוד נוחה. על זה אני מתכוון לשים את הדגש.
אני יודע שאני מפסיד בביצועים, אבל המטרה שלי כאן היא כתיבת קוד קלה.
דברים מרכזיים:
1. ה-action מקבל כפרמטרים את הפרמטרים שנשלחו בבקשה (get/post) (שליחת הפרמטרים היא לפי השמות שלהם ולא לפי הסדר, מה שנוח מאוד).
2. יש מיפוי של הפרמטרים לאובייקטים. אפשר לראות ב-action היחיד שיש לי שם כרגע, שאני מקבל אובייקט מסוג RegisterForm. מה שקורה הוא שנוצר אובייקט RegisterForm חדש ושהפרמטרים (get/post) ממלאים את ה-properties שלו. ובכך אנחנו מקבלים ל-action אובייקט RegisterForm.
3. ניתוח של ה-phpdoc במאפיינים של models. אם ניכנס ל-RegisterForm אפשר לראות שלכל מאפיין יש דוקומנטציה שבסופו של דבר משפיעה על האפליקציה באופן ישיר. אני קובע דרך שם חוקי ואלידציה, הודעות שגיאה, שמות תצוגה וכו'.
4. כהמשך ל-3, יש namespace בשם Validators שמכיל בתוכו את כל הואלידטורים. כרגע יש שם רק את הואלידאטור הבסיסי, שהוא משמש כברירת מחדל.
5. מחלקת HtmlHelper לטיפול נוח בפקדי html. המחלקה הזו מתואמת עם המאפיינים של המודל ואפשר ליצור איתה פקדי html שמקושרים או לא מקושרים למאפיינים של ה-model בצורה נוחה מאוד. אפשר לראות שימוש שלה בשני ה-views שיש לי שם.
אשמח לקבל ביקורת טובה/רעה, הצעות לשיפור.
ודבר נוסף - לא סתם זה ב-github. אם מישהו רוצה להצטרף לפיתוח הוא תמיד מוזמן.
7 תשובות
קודם כל - שאפו על השימוש הנכון בניימספייס.
אני רואה קיבלת השראה פה ושם מכל מיני פריימוורקים, שזה רעיון חכם :)
השימוש בלייזי לואדינג (aka autoload) הוא שימוש רצוי, אך יש (מהרפרוף שלי) קצת הרבה שימוש בincludeים
מיותרים, שלדעתי אפשר להפיל על הautoloader ולחסוך עוד כמה שורות של קוד
השימוש שוב הוא בסדר גמור, וכמובן שיש מקרים שהקבצים שאתה רוצה לאנקלד לא תואמים לתקן psr-0 ככה שחייב לרשום
את הנתיב לקובץ, אבל לפי מה שאני ראיתי לא היה לך בעיות של תאימות ולדעתי אתה יכול אפילו לכתוב קלאס שישמש נטו לאאטולואדינג יותר מתוחכם. אני אישית כשעבדתי על פרויקט קטן לאחרונה פשוט לקחתי את הautoloader של לרבל, והתלבשתי עליו. לא חייב להתלבש עליו, אבל הוא יכול להווה אחלה מקור לרעיונות.
קונטרולרים:
עשית שם עבודה בסדר לחלוטין, רק הערה קטנה בנוגע לקובץ הראשי (Controller.php):
יש שם המון מטודות של setTitle, setAuthor וכו'. לדעתי האישית זה design לא נכון, כי קונטרולר לא אמור להיות אחראי לצד של הנתוני view האלה אלא דווקא הקלאס view שלך ששם זה בהחלט לגיטימי לשים את כל זה וכמובן שאת addJs, addCss וכו'. אם בכלל הולכים על design נכון יותר אפשר להפריט את הנושאים - כל החלק של הקבצים הסטטים אפשר ליצור lib נפרד שיקרא assets וינהל את כל העיניין של הקבצים הסטטים הנ"ל, ובאותה מידה אולי lib ל-"html" שיהווה לא בהכרח בניית forms וכדומה אלא גם יאפשר ניהול טאגים בסיסים כמו שציינת שם.
בסופו של דבר כשאתה מתכנן מערכת זה די חשוב להפריט ולראות האם באמת הדברים האלה קשורים למה שצריך.
בקובץ view שוב חוזרת הנקודה של האאוטולואדינג, אבל חוץ מזה נראה בסדר. מה שכן ראיתי יש לך את התנאי
נגיד ויש לי סטייל של שמות כאלה: register_index.php, register_step1.php, register_last.php ולפי מה שאני רואה התנאי שלך יזרוק אותי פשוט החוצה. אלא אם כן באמת חשוב לך מסיבה כלשהי שקשורה למערכת שיהיה את הסטנדרט הזה, אני לא חושב שיש סיבה להחזיק בתנאי הזה.
חוץ מזה יש עוד כמה נקודות:
error & exception handler - דבר שדי רצוי לממש, להקל על ניהול השגיאות בצורה יותר יעילה וגם לאפשר לזרוק לתוך קובץ לוגים ולהדפיס שגיאה יפה ללקוח הסופי.
מחלקת request היא מחלקה בהחלט נחמדה, ומקיפה דברים, אבל כמו כן יש סיפרייה ממש נחמדה של סימפוני בשם HttpFoundation, שהיא קלה להטמעה וכמו כן לשימוש. הסיפרייה מקיפה ברמות את כל מה שקשור לעבודה מול Request וResponse בצורות שמכסות ממש את הכל. בכל פעם שיש לי צורך בשימוש בדברים האלה - אני לא חושב פעמיים ומשתמש בה.
כמו כן שוב design, העיצוב שעשית הוא בסדר גמור, אבל לדעתי צריך להסתכל יותר לכיוון האם זה באמת קשור למחלקה הנוכחית, האם המבנה של התיקיות נכון, האם באמת צריך פה traits, האם הקלאס הזה הוא בכלל צריך להיות משהו אבסטרקטי, אולי צריך לדחוף פה אינטרפייס איפשהו, האם התשתית הזאת מספיק גמישה לפרויקטים קצת יותר מסובכים. יש קצת בלבול עם הקבצים לדעתי, ברמת הסידור של המבנה תיקיות אבל זה לא משהו קריטי במיוחד.
בסופו של דבר OO הוא דבר מופלא, ויש לו המון אפשרויות של deisgn, צריך רק לקרוא וללמוד :)
חוץ מזה בתור התחלה עשית פה אחלה בסיס, אחלה עבודה ובאמת שאפו על זה.
כמו כן אשמח לקבל תמיד את דעתך על התגובה שלי, ותמיד יכול להיות שאני טועה אז לא לקחת אותי כמובן מאליו בכל דבר
עוד משהו שרציתי לציין, עמוד הindex.php
לדעתי גם שם הdesign הוא לא הכי נכון - הגדרת הקונטרולר הדיפולטי וכמו כן הגדרת הaction הדפילוטי לא אמורה להיות מוגדרת שם. הrewrite שעשית הוא בסדר לחלוטין, אבל אני רואה מכאן איך אפשר לעשות את זה יותר גמיש ולהוסיף גם מחלקת ניתוב שתאפשר אפילו יותר גמישות. בכל מקרה יש המון לאן לזרום מכאן, פשוט צריך לראות איך פריימוורקים אחרים מטפלים בכל העיניין הזה ולתת לרעיונות לזרום :)
קודם כל, דעתי על התגובה שלך: תודה רבה, מעריך מאוד תגובות מושקעות. זו מסוג התגובות שלקרוא ולהבין את כולן ולהסיק את כל המסקנות מהן לוקח הרבה יותר מקריאה אחת. באמת תודה רבה! :)
autoloader:
כרגע זה משהו בסיסי ביותר שמסתמך על הרעיון שמבנה הקבצים והתיקיות זהה למבנה של ה-namespaceים.
אבל אני בהחלט מסכים איתך שיהיה ראוי למממש autoloader מקיף יותר. אני אסתכל בזה של לרבל.
קונטרולרים:
אתה צודק. בהתחלה לא הייתה בכלל מחלקת View ונוצר מצב שהרבה דברים ששייכים ל-view הופיעו בקונטרולר (כן, גם המתודה render).
View:
התנאי הזה הוא יותר עניין אבטחתי מאשר סטנדרט קבוע. לא רציתי לאפשר מצבים שאני מקבל view כזה: System/App.php/.. ויוצא שאני טוען את App במקום איזשהו view.
ככה שכדי להמנע מהשטויות האלה, בדקתי שהוא מכיל תווים מסוימים. אני אוסיף לשם עוד תווים (קו תחתון, מספרים וכו').
error & exception handler:
תוכל לראות ב-index שהכל עטוף ב-try.. catch. מה שאני כן מתכנן הוא תפיסה של כל ה-errorים ש-php זורקת (לא Exceptions) ולהמיר אותם ל-Exceptions.
request:
אני גם אבדוק את HttpFoundation, אולי אני אבחר באמת להטמיע אותה אצלי, או שאולי אני רק אקח רעיונות.
תודה, לא ההכרתי את זה.
index.php:
האמת היא שאני מתכוון די להעיף אותו. אם מישהו משתמש בפריימוורק אני לא רוצה לקבע אותו ל-index ספציפי.
אני מתכוון למממש מחלקת Bootstrap או משהו בסגנון, ככה שב-index יהיה אפשר פשוט להפעיל אותה וזה הכל.
בנוגע להגדרות של הדיפולטים - אני אעביר את זה ל-config.
תודה רבה, גם לשאר ההערות שלא הגבתי עליהן אני לקחתי לתשומת לבי ואני אשתדל לשפר.
שוב תודה. :)
עשיתי שינויים.
יש עכשיו תמיכה הרבה הרבה יותר טובה ב-annotations.
ושיפרתי את ה-validators.
1) לא אהבתי את הצורה של הטפסים שעשית (שאותה ראיתי ב-View/register).
<?= $html->textBoxFor('username') ?>
הפונקציות האלו לא עוזרות ממש כאשר אתה עדיין צריך לכתוב כל מה שאתה רוצה בנפרד.
תעשה אפשרות שתתן לך ליצור פונקציות משלך ליצירת אלמנטים, שתוכל לדוגמא לעשות פונקציה משלך שמאפשר יצירה של אינפוט ושל לבל ביחד.
// $html->addHelper('input',['string $name','string $value','string $text','array $attrs'],'createInput');
// $html->addHelper('input',['string $name','string $value','string $text'],'createInput',['attrs'=>[]]);
// $html->addHelper('input',['string $name','string $value'],'createInput',['attrs'=>[],'withoutLabel'=>true]);
(בדוגמא הצהרה לפונקציה - כאשר פרמטר מוקף בהצרה בסוגריים מרובעות זה אומר שהוא לא חובה)
(הקוד שיש שם הוא ההצהרה, וכל מה שנמצא בתוך הערה אלו דוגמאות למימוש)
(יש פה העמסת פונקציות עפ"י הפרמטרים שהפונקציה addHelper צריכה לעשות בעזרת הפרמטר $params)
(זה לא מבוצע פה עד הסוף, זה סה"כ דוגמא ואים עליה ממש עקביות איך זה יבוצע מבחינת הפונקציה addHelper)
($funcParams מאפשר לשלוח לפונקציה $func פרמטרים שלא נמצאים ב$params)
2) בקונטרולר, באקשיין: למה לבדוק את המתודה ואת הטופס בפונקציה אם אפשר לשדרג קצת את המערכת כדי לעשות ככה (עם קצת שדרוג של ה-validator):
* The Index action.<br />
* @url: GET /Index/Index
*/
public function IndexFormAction() {/* form */}
/**
* The Index action.<br />
* @url: POST /Index/Index
* @validator use($form->isValid())
* @else: GET /Index/Index
*/
public function IndexFormAction(RegisterForm $form) {/* show */}
(כאשר ב-validator, הפונקציה use מאפשרת להמשיך כאשר תנאי כלשהו שווה ל-true, תוך כדי שימוש בפרמטרים שפונקציית האקשן מקבלת (לפני שהיא מופעלת))
(כאשר @else מציין פקודה שצריך לעשות אם ה-validator לא נכון.
1. האמת היא שהרעיון הזה לא שלי, זה סגנון של דוט נט והוא מאוד נפוץ.
ולא הבנתי מה המטרה של addHelper, מה זה נותן לי?
2. אין method-overloading ב-php לצערי. ולכן תקבל שגיאה כשתיצור שתי מתודות עם אותו השם. אם זה היה קיים (כמו ב-c# למשל), אז סביר לראות שהיית רואה בפריימוורק דבר כזה:
* @RequestMethod POST
*/
public function IndexAction() {}
public function IndexAction(RegisterForm $form) {}
כמו בדוט נט.
תודה רבה על ההצעות, אבל את הראשונה לא כל כך הבנתי ואת השניה אי אפשר לממש (בצורה נורמלית, בלי לשנות את הקוד בזמן ריצה).
1.1.1) בדוטנט האלמנט מופיע כאלמנט HTML עם ניימספייס ASP, מה שהופך את הקוד ליותר מובן הרי אנחנו בטוחים שזה יציג לנו אלמנט שבצד לקוח.
1.1.2) בדוטנט, הדבר המרכזי שבגללו יש את זה הוא כי בעזרת הדברים האלו אפשר לעשות קשר בין אלמנטי הצד לקוח שכתובים עם ניימספייס asp לקוד C#/VB.NET, ובכך לשלוט בצד לקוח דרך הצד שרת.
1.2) זה מעיין אפשרות ליצור "תגים" משלך שיעשו מה שאתה רוצה.
תאר לך שהיית יכול בעזרת תג <panel> ותג <tab> ליצור אלמנט משלך שיעשה פאנל של טאבים, בלי התעסקות בקוד עצמו של הפאנל שכתוב בHTML.
במילים אחרות: הקוד שאתה כותב עם התגים שיצרת יהפוך לקוד HTML מבלי שתצטרך לכתוב את כולו.
<x:panel>
<x:tab title="tab 1">content of tab 1</x:tab>
<x:tab title="tab 2">content of tab 2</x:tab>
</x:panel>
$html->xPanel(
$html->xTab('tab 1','content of tab 1'),
$html->xTab('tab 2','content of tab 2')
);
הדבר הזה קיים בהרבה פריימוורקים של צד לקוח והוא מאוד שימושי.
2) טעות שלי - התכוונתי לכתוב את המתודות בשמות שונים (IndexFormAction, IndexShowAction) וככה למנוע דריסה של מתודות.
התכוונתי שהפריימוורק יפענח את הדרישות של האקשן ויבחר בעצמו איזו מתודה להריץ.